import 'dart:convert';

import 'package:lib_common/lib_common.dart';
import 'package:lib_http/lib_http.dart';

class UserNotifier extends StateNotifier<UserModel?> {
  UserNotifier(super.state);

  void update(UserModel? userModel) {
    UserManager.getInstance()._updateUser(userModel);
    state = userModel;
  }
}

class UserManager {
  UserManager._();

  // 单例实例
  static final UserManager _instance = UserManager._();

  // 工厂构造函数
  factory UserManager.getInstance() {
    return _instance;
  }

  final userNotifier = StateNotifierProvider<UserNotifier, UserModel?>((ref) => UserNotifier(null));

  UserModel? _userModel;

  void _updateUser(UserModel? userModel) {
    _userModel = userModel;
  }

  /// 初始化检查用户信息
  Future<void> loadUserInfo(WidgetRef ref) async {
    var userToken = SpUtil.getString(CacheConstants.userToken) ?? "";
    if (userToken.isNotEmpty) {
      LogUtils.v("loadUserInfo->token:$userToken");
      var userJson = SpUtil.getString(userToken) ?? "";
      if (userJson.isNotEmpty) {
        LogUtils.v("loadInfoFromLocal->userinfo:$userJson");
        var userModel = UserModel.fromToken(userJson);
        var decode = json.decode(userJson);
        // 读取本地缓存数据
        userModel.loadInfoFromLocal(decode);
      }
      await _fetchUserInfoFromNet(ref);
    }
  }

  Future<dynamic> _fetchUserInfoFromNet(WidgetRef ref) async {
    var token = SpUtil.getString(CacheConstants.userToken) ?? "";
    var userModel = UserModel.fromToken(token);
    var userInfoResult = await HttpManager.getInstance().getAsync(HttpUrls.userInfo);
    if (userInfoResult is Map<String, dynamic>) {
      userModel.configInfo(userInfoResult);
    } else {
      LogUtils.e("userInfoResult:${userInfoResult.runtimeType}, data:$userInfoResult");
    }
    var vipInfoResult = await HttpManager.getInstance().getAsync(HttpUrls.vipInfo);
    if (vipInfoResult is Map<String, dynamic>) {
      userModel.configVip(vipInfoResult);
    } else {
      LogUtils.e("vipInfoResult:${vipInfoResult.runtimeType}, data:$vipInfoResult");
    }
    var checkRechargeResult = await HttpManager.getInstance().getAsync(HttpUrls.checkRecharge, pretreatment: false);
    if (checkRechargeResult is Map<String, dynamic>) {
      userModel.paid = checkRechargeResult["status"] == 1;
    } else {
      LogUtils.e("checkRechargeResult:${checkRechargeResult.runtimeType}, data:$checkRechargeResult");
    }
    var complete = userModel.dataComplete();
    LogUtils.v("complete:$complete,UserInfo:${userModel.toString()}");
    if (complete) {
      await SpUtil.putString(CacheConstants.userToken, userModel.token!);
      await SpUtil.putString(userModel.token!, jsonEncode(userModel));
      ref.refresh(userNotifier.notifier).update(userModel);
      return userModel;
    } else {
      return null;
    }
  }

  void updatePlayTime(WidgetRef ref, {bool force = true, ValueChanged<bool>? callback}) async {
    var vipInfoResult = await HttpManager.getInstance().getAsync(HttpUrls.vipInfo, params: {'cache': force ? "0" : "1", "is_refresh": force});
    if (vipInfoResult is Map<String, dynamic>) {
      _userModel?.configVip(vipInfoResult);
      ref.refresh(userNotifier.notifier).update(_userModel);
      callback?.call(true);
    } else {
      LogUtils.e("vipInfoResult:${vipInfoResult.runtimeType}, data:$vipInfoResult");
      callback?.call(false);
    }
  }

  void loginByWeChat(WidgetRef ref, String? authCode, {ValueChanged<bool>? callback}) async {
    var data = await _buildUniParams({"code": authCode});
    HttpManager.getInstance().post(
      HttpUrls.loginByWeChat,
      data: data,
      pretreatment: false,
      startCallback: () {
        SmartDialog.showLoading(msg: "");
      },
      successCallback: (response) async {
        if (response is Map) {
          var tokenData = response["newToken"];
          if (tokenData is Map) {
            var token = tokenData["token"];
            if (token is String) {
              await SpUtil.putString(CacheConstants.userToken, token);
              var result = await _fetchUserInfoFromNet(ref);
              if (result is UserModel) {
                callback?.call(true);
                return;
              }
            }
          }
        }
        callback?.call(false);
      },
      errorCallback: (error) {
        callback?.call(false);
      },
      finishCallback: () {
        SmartDialog.dismiss();
      },
    );
  }

  /// 是否登录
  bool isLogin() {
    if (_userModel == null) {
      return false;
    }
    return _userModel?.token?.isNotEmpty ?? false;
  }

  /// 是否充值用户
  bool isRechargeUser() {
    if (_userModel == null) {
      return false;
    }
    return _userModel?.paid ?? false;
  }

  /// 获取用户高峰时长
  int getUserPlayTime() {
    if (_userModel == null) {
      return 0;
    }
    return _userModel?.totalTime ?? 0;
  }

  int getUserVipExpiredTime() {
    if (_userModel == null) {
      return 0;
    }
    return _userModel?.vipEndDate ?? 0;
  }

  /// 获取用户id
  String getUserId() {
    if (_userModel == null) {
      return "";
    }
    return _userModel?.userId ?? "";
  }

  /// 获取用户Token
  String getUserToken() {
    if (_userModel == null) {
      return "";
    }
    return _userModel?.token ?? "";
  }

  /// 是否新用户
  String isNewUser() {
    if (_userModel == null) {
      return "";
    }
    var sameDay = TimeUtils.isSameDay(_userModel?.registerDate ?? 0, TimeUtils.getRealTime());
    return sameDay ? "new" : "old";
  }

  String getUserLevel() {
    if (_userModel == null) {
      return "1";
    }
    return _userModel?.level ?? "1";
  }

  int getRegisterDate() {
    if (_userModel == null) {
      return 0;
    }
    return _userModel?.registerDate ?? 0;
  }

  bool checkAuthentication() {
    if (_userModel == null) {
      return false;
    }
    return _userModel?.authenticated ?? false;
  }

  Future<void> logout(WidgetRef ref) async {
    if (_userModel != null && _userModel!.token != null) {
      SpUtil.putString(_userModel!.token!, "");
    }
    await SpUtil.putString(CacheConstants.userToken, "");
    ref.refresh(userNotifier.notifier).update(null);
  }

  Future<Map<String, dynamic>> _buildUniParams(Map<String, String?> params) async {
    var deviceID = await getDeviceId();
    Map<String, dynamic> data = {
      "clientInfo": {
        "uniPlatform": "app",
        "appId": AppManager.getInstance().getAppId(),
        "deviceId": deviceID,
      },
      "params": params,
    };
    if (isLogin()) {
      data["uniIdToken"] = _userModel?.token;
    }
    return data;
  }

  Future<String> getDeviceId() async {
    var deviceId = SpUtil.getString(CacheConstants.deviceId) ?? "";
    if (deviceId.isNotEmpty) {
      return deviceId;
    } else {
      deviceId = const Uuid().v4();
      await SpUtil.putString(CacheConstants.deviceId, deviceId);
      return deviceId;
    }
  }
}
